package middleware

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/Sir-yuChen/funAnalyse/global"
	"github.com/Sir-yuChen/funAnalyse/global/redisEnums"
	"github.com/Sir-yuChen/funAnalyse/model"
	"github.com/Sir-yuChen/funAnalyse/model/common/ApiReturn"
	"github.com/Sir-yuChen/funAnalyse/model/common/response"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"time"
)

func CasbinMiddleware() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		// 获取请求的URI
		obj := ctx.Request.URL.RequestURI()
		// 获取请求方法
		act := ctx.Request.Method
		// 获取用户的角色
		roles := getUserRoles(ctx)
		success := false
		for _, role := range roles {
			if role.Status == "N" {
				continue
			}
			if success {
				continue
			}
			sub := role.RoleId
			// 判断策略中是否存在
			t, e := global.GVA_CASBIN.Enforce(sub, obj, act, "Y")
			if e != nil {
				global.GVA_LOG.Error("策略校验异常", zap.String("path", obj), zap.String("method", act), zap.Error(e))
			}
			success = t
		}
		if success {
			ctx.Next()
		} else {
			global.GVA_LOG.Warn("请求无权限,接口被拦截", zap.String("path", obj), zap.String("method", act))
			response.WithApiReturn(ApiReturn.NoPermission, ctx)
			ctx.Abort()
			return
		}
	}
}
func getUserRoles(ctx *gin.Context) []model.StockCasbinRoleRelationUserModel {
	customerId, _ := ctx.Get("customerId")
	key := fmt.Sprint(customerId) + redisEnums.USER_ROLE_KEY_SUFFIX
	var roleIds []model.StockCasbinRoleRelationUserModel

	result, err := global.GVA_REDIS.Exists(context.Background(), key).Result()
	if err != nil {
		global.GVA_LOG.Warn("casbin 资源权限认证", zap.Any("customerId", customerId), zap.String("key", key), zap.Error(err))
		ctx.Abort()
		return nil
	}
	if result <= 0 {
		//key 不存在，查数据库
		if e := global.GVA_DB.Model(model.StockCasbinRoleRelationUserModel{}).Where(" user_id = ? ", customerId).Find(&roleIds).Error; e != nil {
			global.GVA_LOG.Error("casbin redis无用户角色关联信息查DB 异常", zap.Any("customerId", customerId), zap.Error(e))
			ctx.Abort()
			return nil
		}
		if roleIds != nil {
			timer := time.Duration(global.GVA_CONFIG.JWT.RedisExpiresTime) * time.Second
			global.GVA_REDIS.Set(context.Background(), key, roleIds, timer)
		}
	} else {
		//缓存中获取
		jsonStr, err := global.GVA_REDIS.Get(context.Background(), key).Result()
		if err != nil {
			global.GVA_LOG.Error("casbin 获取缓存中用户角色关联关系 异常", zap.Any("customerId", customerId), zap.String("key", key), zap.Error(err))
			ctx.Abort()
			return nil
		}
		if err = json.Unmarshal([]byte(jsonStr), &roleIds); err != nil {
			global.GVA_LOG.Error("casbin 数据转换异常 异常", zap.Any("customerId", customerId), zap.String("key", key), zap.Error(err))
			ctx.Abort()
			return nil
		}
	}
	return roleIds
}
